package com.codeest.geeknews.di.module;

import com.codeest.geeknews.BuildConfig;
import com.codeest.geeknews.app.Constants;
import com.codeest.geeknews.di.convert.fastjson.FastJsonConvertFactory;
import com.codeest.geeknews.di.convert.json.JsonConverterFactory;
import com.codeest.geeknews.di.convert.string.StringConverterFactory;
import com.codeest.geeknews.di.qualifier.DoubanLoginUrl;
import com.codeest.geeknews.di.qualifier.DoubanV2Url;
import com.codeest.geeknews.di.qualifier.GankUrl;
import com.codeest.geeknews.di.qualifier.GoldUrl;
import com.codeest.geeknews.di.qualifier.LastfmUrl;
import com.codeest.geeknews.di.qualifier.MyUrl;
import com.codeest.geeknews.di.qualifier.VtexUrl;
import com.codeest.geeknews.di.qualifier.WechatUrl;
import com.codeest.geeknews.di.qualifier.ZhihuUrl;
import com.codeest.geeknews.model.http.api.DoubanLoginApis;
import com.codeest.geeknews.model.http.api.DoubanV2Apis;
import com.codeest.geeknews.model.http.api.GankApis;
import com.codeest.geeknews.model.http.api.GoldApis;
import com.codeest.geeknews.model.http.api.LastfmApis;
import com.codeest.geeknews.model.http.api.MyApis;
import com.codeest.geeknews.model.http.api.VtexApis;
import com.codeest.geeknews.model.http.api.WeChatApis;
import com.codeest.geeknews.model.http.api.ZhihuApis;
import com.codeest.geeknews.util.SystemUtil;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by codeest on 2017/2/26.
 */

/**
 * 空构造函数
 * App#getAppComponent 中new HttpModule() 完成实例化
 * <p>
 * 提供网络请求相关实例
 */
@Module
public class HttpModule {


    @Singleton
    @Provides
    Retrofit.Builder provideRetrofitBuilder() {
        return new Retrofit.Builder();
    }


    @Singleton
    @Provides
    OkHttpClient.Builder provideOkHttpBuilder() {
        return new OkHttpClient.Builder();
    }

    @Singleton
    @Provides
    @ZhihuUrl
    Retrofit provideZhihuRetrofit(Retrofit.Builder builder, OkHttpClient client) {
        return createRetrofit(builder, client, ZhihuApis.HOST);
    }

    @Singleton
    @Provides
    @WechatUrl
    Retrofit provideWechatRetrofit(Retrofit.Builder builder, OkHttpClient client) {
        return createRetrofit(builder, client, WeChatApis.HOST);
    }

    @Singleton
    @Provides
    @GankUrl
    Retrofit provideGankRetrofit(Retrofit.Builder builder, OkHttpClient client) {
        return createRetrofit(builder, client, GankApis.HOST);
    }

    @Singleton
    @Provides
    @GoldUrl
    Retrofit provideGoldRetrofit(Retrofit.Builder builder, OkHttpClient client) {
        return createRetrofit(builder, client, GoldApis.HOST);
    }

    @Singleton
    @Provides
    @VtexUrl
    Retrofit provideVtexRetrofit(Retrofit.Builder builder, OkHttpClient client) {
        return createRetrofit(builder, client, VtexApis.HOST);
    }

    @Singleton
    @Provides
    @LastfmUrl
    Retrofit provideLastfmRetrofit(Retrofit.Builder builder, OkHttpClient client) {
        return createRetrofit(builder, client, LastfmApis.HOST);
    }

    @Singleton
    @Provides
    @DoubanLoginUrl
    Retrofit provideDoubanLoginRetrofit(Retrofit.Builder builder, OkHttpClient client) {
        return createRetrofit(builder, client, DoubanLoginApis.HOST);
    }

    @Singleton
    @Provides
    @DoubanV2Url
    Retrofit provideDoubanV2Retrofit(Retrofit.Builder builder, OkHttpClient client) {
        return createRetrofit(builder, client, DoubanV2Apis.HOST);
    }

    @Singleton
    @Provides
    @MyUrl
    Retrofit provideMyRetrofit(Retrofit.Builder builder, OkHttpClient client) {
        return createRetrofit(builder, client, MyApis.HOST);
    }

    @Singleton
    @Provides
    OkHttpClient provideClient(OkHttpClient.Builder builder) {
        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            //loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);//只打印网络请求
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//打印网络请求和返回结果
            builder.addInterceptor(loggingInterceptor);
        }
        File cacheFile = new File(Constants.PATH_CACHE);//设置缓存文件路径
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);//缓存文件最大限制大小50M
        Interceptor cacheInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (!SystemUtil.isNetworkConnected()) {//没网强制从缓存读取(必须得写，不然断网状态下，退出应用，或者等待一分钟后，就获取不到缓存）
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                }
                Response response = chain.proceed(request);
                //Response responseLatest;
                //缓存策略http://www.cnblogs.com/_franky/archive/2011/11/23/2260109.html
                if (SystemUtil.isNetworkConnected()) {
                    int maxAge = 0;
                    // 有网络时, 不缓存, 最大保存时长为0(或者有网失效一分钟则 maxAge = 60)
                    //responseLatest =  response.newBuilder()
                    response = response.newBuilder()
                            .removeHeader("Pragma")
                            .removeHeader("Cache-Control")
                            .header("Cache-Control", "public, max-age=" + maxAge)
                            //.removeHeader("Pragma")
                            .build();
                } else {
                    // 无网络时，设置超时为4周
                    int maxStale = 60 * 60 * 24 * 28;
                    //responseLatest =  response.newBuilder()
                    response = response.newBuilder()
                            .removeHeader("Pragma")
                            .removeHeader("Cache-Control")
                            .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                            //.removeHeader("Pragma")
                            .build();
                }
                return response;//直接返回了之前的response是达不到缓存目的的
                //return responseLatest;//直接返回了之前的response是达不到缓存目的的
            }
        };
//        Interceptor apikey = new Interceptor() {
//            @Override
//            public Response intercept(Chain chain) throws IOException {
//                Request request = chain.request();
//                request = request.newBuilder()
//                        .addHeader("apikey",Constants.KEY_API)
//                        .build();
//                return chain.proceed(request);
//            }
//        }
//        设置统一的请求头部参数
//        builder.addInterceptor(apikey);
        //设置缓存
        builder.addNetworkInterceptor(cacheInterceptor);//okhttp只会对get请求进行缓存，post请求是不会进行缓存，这也是有道理的，因为get请求的数据一般是比较持久的，而post一般是交互操作，没太大意义进行缓存。
        builder.addInterceptor(cacheInterceptor);
        builder.cache(cache);
        //设置超时
        builder.connectTimeout(10, TimeUnit.SECONDS);
        builder.readTimeout(20, TimeUnit.SECONDS);
        builder.writeTimeout(20, TimeUnit.SECONDS);
        //错误重连
        builder.retryOnConnectionFailure(true);
        return builder.build();
    }

    @Singleton
    @Provides
    ZhihuApis provideZhihuService(@ZhihuUrl Retrofit retrofit) {
        return retrofit.create(ZhihuApis.class);
    }

    @Singleton
    @Provides
    GankApis provideGankService(@GankUrl Retrofit retrofit) {
        return retrofit.create(GankApis.class);
    }

    @Singleton
    @Provides
    WeChatApis provideWechatService(@WechatUrl Retrofit retrofit) {
        return retrofit.create(WeChatApis.class);
    }

    @Singleton
    @Provides
    GoldApis provideGoldService(@GoldUrl Retrofit retrofit) {
        return retrofit.create(GoldApis.class);
    }

    @Singleton
    @Provides
    VtexApis provideVtexService(@VtexUrl Retrofit retrofit) {
        return retrofit.create(VtexApis.class);
    }

    @Singleton
    @Provides
    LastfmApis provideLastfmService(@LastfmUrl Retrofit retrofit) {
        return retrofit.create(LastfmApis.class);
    }

    @Singleton
    @Provides
    DoubanLoginApis provideDoubanLoginService(@DoubanLoginUrl Retrofit retrofit) {
        return retrofit.create(DoubanLoginApis.class);
    }

    @Singleton
    @Provides
    DoubanV2Apis provideDoubanV2Service(@DoubanV2Url Retrofit retrofit) {
        return retrofit.create(DoubanV2Apis.class);
    }

    @Singleton
    @Provides
    MyApis provideMyService(@MyUrl Retrofit retrofit) {
        return retrofit.create(MyApis.class);
    }

    private Retrofit createRetrofit(Retrofit.Builder builder, OkHttpClient client, String url) {
        return builder
                .baseUrl(url)
                .client(client)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(StringConverterFactory.create())
                .addConverterFactory(JsonConverterFactory.create())
                .addConverterFactory(FastJsonConvertFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
}
